﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Web.UI.WebControls;
using Trentacular.SharePoint.Util;
using Trentacular.SharePoint.Web.UI.WebControls;

namespace Trentacular.SharePoint.Web.UI.UserControls
{
    public partial class PropertiesEditor : BaseSPUserControl
    {
        public enum PropertiesScope
        {
            [Description("Site")]
            Web,
            Farm
        }

        /// <summary>
        /// Gets or sets the scope of the properties to operate on.
        /// </summary>
        /// <value>The scope of the properties to operate on.</value>
        public PropertiesScope Scope { get; set; }

        private bool RedirectNeeded = false;

        #region Events

        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
                gvProperties.Sort("Key", SortDirection.Ascending);
        }

        protected void Page_PreRender(object sender, EventArgs e)
        {
            if (RedirectNeeded)
                Response.Redirect(Request.RawUrl);

            litDescription.Visible = (Scope == PropertiesScope.Web);
        }

        protected void btnAdd_Click(object sender, EventArgs e)
        {
            var key = txtKey.Text;
            var value = txtValue.Text;

            AddProperty(key, value);

            RedirectNeeded = true;
        }

        #endregion

        #region Data Source Methods

        protected void GetProperties(DelegateSelectArguments args)
        {
            args.Results = GetProperties().Cast<DictionaryEntry>()
                .Select(de => new KeyValuePair<string, string>(
                    de.Key.ToString(),
                    de.Value.ToString())
                )
                .ToArray();
        }

        protected void UpdateProperty(DelegateUpdateArguments args)
        {
            var key = (string)args.Keys["Key"];
            var value = (string)args.Values["Value"];
            var oldValue = (string)args.OldValues["Value"];

            if (value == oldValue)
            {
                args.ResultCount = 0;
                return;
            }

            UpdateProperty(key, value);
            args.ResultCount = 1;

            RedirectNeeded = true;
        }

        protected void DeleteProperty(DelegateDeleteArguments args)
        {
            var key = (string)args.Keys["Key"];

            DeleteProperty(key);
            args.ResultCount = 1;

            RedirectNeeded = true;
        }

        #endregion

        #region CRUD Methods

        private Hashtable GetProperties()
        {
            switch (Scope)
            {
                case PropertiesScope.Web:
                    return Web.AllProperties;
                case PropertiesScope.Farm:
                    var farm = Web.Site.WebApplication.Farm;
                    return farm.Properties;
            }

            throw new ArgumentException();
        }

        private void UpdateProperty(string key, string value)
        {
            switch (Scope)
            {
                case PropertiesScope.Web:
                    Web.AddPropertyAndUpdate(key, value);
                    break;
                case PropertiesScope.Farm:
                    var farm = Web.Site.WebApplication.Farm;
                    farm.Properties[key] = value;
                    farm.Update();
                    break;
            }
        }

        private void DeleteProperty(string key)
        {
            switch (Scope)
            {
                case PropertiesScope.Web:
                    Web.RemovePropertyAndUpdate(key);
                    break;
                case PropertiesScope.Farm:
                    var farm = Web.Site.WebApplication.Farm;
                    farm.Properties.Remove(key);
                    farm.Update();
                    break;
            }
        }

        private void AddProperty(string key, string value)
        {
            switch (Scope)
            {
                case PropertiesScope.Web:
                    Web.AddPropertyAndUpdate(key, value);
                    break;
                case PropertiesScope.Farm:
                    var farm = Web.Site.WebApplication.Farm;
                    farm.Properties[key] = value;
                    farm.Update();
                    break;
            }
        }

        #endregion
    }
}
